
package com.ceba.test.webservice.service.impl;

import abc.ID;
import abc.util.FileHelper;
import com.ceba.base.enums.FileStorageFalgeEnum;
import com.ceba.base.helper.LoggerHelper;
import com.ceba.base.utils.*;
import com.ceba.cebacer.KeyLoaderType;
import com.ceba.cebautils.DateUtil;
import com.ceba.cebautils.StringUtil;
import com.ceba.test.base.config.LogicPathUtil;
import com.ceba.test.base.configs.CebaConfig;
import com.ceba.test.base.enums.EditionTypeEnum;
import com.ceba.test.base.language.ResourceUtils;
import com.ceba.test.base.web.response.WebServiceResponseInfo;
import com.ceba.test.modules.admin.entity.*;
import com.ceba.test.modules.log.helper.RestLogHelper;
import com.ceba.test.modules.statistic.entity.ReportSign;
import com.ceba.test.modules.storage.logicService.StorageFileCacheManage;
import com.ceba.test.webservice.entity.Base64File;
import com.ceba.test.webservice.facade.SignFacade;
import com.ceba.test.webservice.facade.SystemFacade;
import com.ceba.test.webservice.service.RestService;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.activation.DataHandler;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import java.io.*;
import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

//http://localhost:18082/ep/cxf/ws?_wadl
@SuppressWarnings("deprecation")
@Path(value="/rs")
@SOAPBinding(style = Style.DOCUMENT)
@WebService(
		targetNamespace = "http://com.ceba.test.webservice.service.impl",
		endpointInterface = "com.ceba.test.webservice.service.RestService", serviceName = "restService")
public class RestServiceImpl implements RestService{

	@Context HttpServletResponse response;
	@Context HttpServletRequest request;

	private static Logger logger = LoggerFactory.getLogger(RestServiceImpl.class);

	//系统配置相关业务接口
	private SystemFacade systemFacade = new SystemFacade();
	//盖章签名相关业务接口
	private SignFacade signFacade = new SignFacade();

	//统计正在签名的数量，防止系统耗尽资源
	private static AtomicInteger signingCnt = new AtomicInteger(0);
	private static int MAX_SIGNING_NUMBER = CebaConfig.MAX_SIGNING_NUMBER_IN_API;
	private static int MAX_SIGNING_EXCEPTION_NUM = 98;

	private boolean isSystemBusy(WebServiceResponseInfo r, String interfaceName) {
		MAX_SIGNING_NUMBER = CebaConfig.MAX_SIGNING_NUMBER_IN_API;
		if (signingCnt.get() > MAX_SIGNING_NUMBER) {
			int waitCnt = 2000;
			int idx = 0;
			while (idx++ < waitCnt) {
				if (signingCnt.get() <= MAX_SIGNING_NUMBER) {
					break;
				} else {
					try {
						logger.info("Curr signing count=" + signingCnt + ", MAX_SIGNING_NUMBER=" + MAX_SIGNING_NUMBER + "This API will be locked.");
						Thread.sleep(2 * 1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
			if (idx >= waitCnt) {
				r.setCode(MAX_SIGNING_EXCEPTION_NUM);
				r.setMessage(ResourceUtils.getMessage("MODULES_UNPROTECTED_IP_ADDRESS_ACCESS"));
				RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, r);
				return true;
			} else {
				logger.info("Curr signing count=" + signingCnt);
				logger.info("MAX_SIGNING_NUMBER=" + MAX_SIGNING_NUMBER);
				logger.info("This API has been released.");
				signingCnt.incrementAndGet();
				return false;
			}
		} else {
			signingCnt.incrementAndGet();
			return false;
		}
	}

	private void freeSystemALittle() {
		signingCnt.decrementAndGet();
	}

	/**
	 * 提交ID和转换为base64格式的文件
	 * created by dingf
	 * @return
	 *  code = 0  签名成功
	 *
	 * code = 1 无法获取证书链
	 * code = 2 证书过期
	 * code = 3 签名企业和初始设置不符
	 * code = 4 签名报告与统计份数不一致
	 * code = 5 无法签名，未激活数字证书签名
	 * code = 6 已超过可签名的最大份数
	 * code = 7 已超过系统可使用期限
	 * code = 8 输入参数不全
	 *
	 * code = 9   上传文件不是PDF文档
	 * code = 10 上传文档超过10M
	 * code = 11 上传文档不存在
	 * code = 12 上传文档已签名
	 * code = 13 插入水印失败
	 * code = 14 公章不存在
	 * code = 15 插入公章失败
	 * code = 16 插入公章、水印时接口异常
	 * code = 17 文档签名失败
	 * code = 18 上传PDF文档异常
	code = 19 水印图片不存在
	code = 20 FTP配置参数不全
	code = 21  从FTP服务器下载文档失败
	code = 22 上传文档到FTP服务器失败

	code = 23 上传文件不存在
	code = 24上传文件BASE64转文件失败
	code = 25 ID不存在
	code = 26 FTPID不存在
	 * code = 30 插入骑缝章失败
	 * code = 31插入骑缝章失败，公章不存在
	 * code = 98 超出系统最大的处理能力MAX_SIGNING_NUMBER
	 * code = 99 不受保护的IP地址访问
	 * code = 100 异常情况
	 */
	@Override
	public String uploadBase64FileAndSignByID(String params) {
		String interfaceName = "uploadBase64FileAndSignByID";
		RestLogHelper.fnStartDebug(Thread.currentThread().getName(),interfaceName);
		logger.info("Payload:" + params);
		WebServiceResponseInfo info = new WebServiceResponseInfo();
		JSONObject result = null;
		String savePath = "";
		String base ="";
		String json = "";
		try {
			params = URLDecoder.decode(params,"utf-8");
			String a = params.substring(params.indexOf("json="), params.indexOf("}&base"));
			json =a.replace("json=", "")+"}";
			String b = params.substring(params.indexOf("base="),params.length());
			base = b.replace("base=", "");
			if (isSystemBusy(info, interfaceName)) {
				result= new JSONObject(info);
				return result.toString();
			}
			if(!systemFacade.isIpInVisited(request)){
				info.setCode(99);
				info.setMessage(ResourceUtils.getMessage("MODULES_UNPROTECTED_IP_ADDRESS_ACCESS"));
				result= new JSONObject(info);
				RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
				return result.toString();
			}

			/**
			 * 系统存储空间已满
			 */
			if (CebaConfig.FILE_STORAGE_FALG == FileStorageFalgeEnum.START) {
				if (!StorageFileCacheManage.isSystemUseStorageAddress()) {
					info.setCode(100);
					info.setMessage(ResourceUtils.getMessage("STORAGE_ADRESS_USE_ORDER_HINT_MESSAGE"));
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, info);
					result= new JSONObject(info);
					return result.toString();
				}
			}


//            synchronized(lock)
			{
				if(StringUtil.isEmptyString(json)){
					info.setCode(8);
					info.setMessage(ResourceUtils.getMessage("MODULES_INPUT_PARAMETER_INCOMPLETE"));
					result= new JSONObject(info);
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
					return result.toString();
				}
				json = URLDecoder.decode(json,"utf-8");
				JSONObject obj = new JSONObject(json);
				ISign[] iSigns = null;
				FTPObject ftp= null;
				String fileName="";
				if(obj.has("sign")){
					if(obj.getJSONObject("sign").has("ID")){
						String iSignId = obj.getJSONObject("sign").getString("ID");
						String[] iSignIds = {iSignId};
						iSigns = new ISign[iSignIds.length];
						info = systemFacade.getSignPDFParamArrayBySignID(iSignIds,iSigns);
						if(info.getCode() !=0){
							result= new JSONObject(info);
							return result.toString();
						}

						//本次签名是否需要数字签名；isSignature=true，需要数字签名
						String isSignature = obj.getJSONObject("sign").has("isSignature")?obj.getJSONObject("sign").getString("isSignature"):"true";
						boolean isOfd = obj.getJSONObject("sign").optBoolean("isOfd", false);
						String validStartOfSeal = obj.getJSONObject("sign").has("validStartOfSeal")?obj.getJSONObject("sign").getString("validStartOfSeal"):"";
						String validEndOfSeal = obj.getJSONObject("sign").has("validEndOfSeal")?obj.getJSONObject("sign").getString("validEndOfSeal"):"";
						String startPageOfQifeng = obj.getJSONObject("sign").has("startPageOfQifeng")?obj.getJSONObject("sign").getString("startPageOfQifeng"):"";
						String endPageOfQifeng = obj.getJSONObject("sign").has("endPageOfQifeng")?obj.getJSONObject("sign").getString("endPageOfQifeng"):"";
						boolean bNeedSig = true;
						if (isSignature.equalsIgnoreCase("false")) {
							bNeedSig = false;
						}
						for (ISign iSign : iSigns) {
							iSign.setNeedSinature(bNeedSig);
							iSign.setShouldOfd(isOfd);
							iSign.setValidStartOfSeal(validStartOfSeal);
							iSign.setValidEndOfSeal(validEndOfSeal);
							iSign.setStartPageOfQifeng(startPageOfQifeng);
							iSign.setEndPageOfQifeng(endPageOfQifeng);
							//从接口入参中获取可复制参数 入参allowPdfContentCopy，true-允许 false-不允许
							systemFacade.setAllowPdfContentCopyFromApiParam(iSign, obj.getJSONObject("sign"));
						}
						//从接口入参中获取控制Api签名时关键字没匹配上是否报错
						systemFacade.setNoErrorNotNormalMatchApiKeyFromApiParam(obj.getJSONObject("sign"));
						//从接口入参中获取控制Api签名时是否添加二维码
						systemFacade.setAllowAddQrFromApiParam(obj.getJSONObject("sign"));
						String resExecCustomDate = executeCustomDate(obj, interfaceName, iSigns);
						if (!resExecCustomDate.isEmpty()) {
							return resExecCustomDate;
						}
					}else{
						info.setCode(25);
						info.setMessage("ID"+ResourceUtils.getMessage("MODULES_NON_EXISTENT"));
						logger.debug(info.getMessage());
						result= new JSONObject(info);
						return result.toString();
					}
					String ftpId = obj.getJSONObject("sign").has("FTPID")?obj.getJSONObject("sign").getString("FTPID"):"";
					if(!StringUtil.isEmptyString(ftpId)){
						ftp = systemFacade.getFTPObjectById(ftpId);
						if(ftp == null){
							info.setCode(26);
							info.setMessage("FTPID"+ResourceUtils.getMessage("MODULES_NON_EXISTENT"));
							result= new JSONObject(info);
							RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
							return result.toString();
						}
						if(!systemFacade.checkFtpValid(ftp)){
							info.setCode(20);
							info.setMessage(ResourceUtils.getMessage("MODULES_FTP_CINFIGURATION_PARAMETER_INCOMPLETE"));
							result= new JSONObject(info);
							RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
							return result.toString();
						}
					}
					fileName = obj.getJSONObject("sign").has("FILE_NAME")?obj.getJSONObject("sign").getString("FILE_NAME"):"default";
				}
				String nowDay = DateUtil.getDayTime("", 0);
				savePath = LogicPathUtil.getPhysicalTempFolder(StorageFileCacheManage.getSystemUseAddressId()) + nowDay+"/";
				if(!FileHelper.exists(savePath)){
					new File(savePath).mkdirs();
				}
				String timestamp = DateUtil.getNowTime(DateUtil.YYYYMMDDHHMMSSS)+ID.get12bID();
				Base64File base64File = new Base64File();
				base64File.setFileName(fileName);
				base64File.setBase64(base);
				if(StringUtil.isEmptyString(base64File.getBase64()) || StringUtil.isEmptyString(base64File.getFileName())){
					info.setCode(23);
					info.setMessage(ResourceUtils.getMessage("MODULES_UPLOAD_PARAMETER_INCOMPLETE"));
					result= new JSONObject(info);
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
					return result.toString();
				}
				RestLogHelper.fnPrintParamDebug(Thread.currentThread().getName(), interfaceName,json, fileName);
				String extName =FileHelper.getFileExtName(fileName);
				if(StringUtil.isEmptyString(fileName)){
					extName = "pdf";
				}
				fileName = FileHelper.getFileName(fileName, false);
				savePath = savePath + fileName +"_"+timestamp+"."+extName;
				int isChange = Base64FileUtils.decoderBase64File(base64File.getBase64(), savePath);
				if(isChange !=0){
					info.setCode(24);
					info.setMessage(ResourceUtils.getMessage("MODULES_UPLOAD_BASE_FILE_FAILED"));
					result= new JSONObject(info);
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
					return result.toString();
				}

				//尝试转换非PDF格式文件
				if (!systemFacade.isPdfFile(extName)) {
					String tmpPath = savePath.replace(extName, "pdf");
					logger.debug("Begin convert " + savePath + " to " + tmpPath);
					ToPdfUtils.fileToPdf(savePath, tmpPath);
					logger.debug("End convert " + savePath + " to " + tmpPath);
					savePath = tmpPath;
				}

				/*if (extName.equalsIgnoreCase("pdf") && !PdfSignUtils.checkFileHasRSASigned(savePath) && !PdfSignUtils.checkFileHasSM2Signed(savePath)) {
					String tmpPath = savePath.replace(".pdf", "-delEncrypt.pdf");
					PdfTools.deletePDFEncrypt(savePath, tmpPath);
					savePath = tmpPath;
				}*/

				info = systemFacade.checkPdfFileAttr(savePath);
				if(info.getCode() !=0){
					result= new JSONObject(info);
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
					return result.toString();
				}

				//获取统计的参数
				ReportSign  parm = systemFacade.packCollectStatisticParm(1, EditionTypeEnum.API.getType(), request.getRemoteAddr());

				//判断是基本模式还是高级模式
				if(iSigns !=null && iSigns.length == 1){
					int key_type = iSigns[0].getKeyType();
					if(key_type == KeyLoaderType.TYPE_CEBA_KEY){
						info = signFacade.checkCanSign();
						if(info.getCode() !=0){
							result= new JSONObject(info);
							return result.toString();
						}

						//下载pdf文档成功，开始插入公章和签名
						info = signFacade.signForUploadFile(iSigns,savePath,ftp, parm);
					}else{
						info = signFacade.dealServerSign(iSigns,savePath,ftp, parm);
					}
				}
			}
		} catch (Exception e) {
			LoggerHelper.error(logger, e, "");
			info.setMessage(ResourceUtils.getMessage("MODULES_INTERFACE_EXCEPTION"));
			info.setCode(100);
		} finally {
			freeSystemALittle();
		}

		result= new JSONObject(info);
		RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
		return result.toString();
	}

	/*
	 * 提交ID和需要签名的文件
	 * created by dingf
	 * code = 0  签名成功
	 *
	 * code = 1 无法获取证书链
	 * code = 2 证书过期
	 * code = 3 签名企业和初始设置不符
	 * code = 4 签名报告与统计份数不一致
	 * code = 5 无法签名，未激活数字证书签名
	 * code = 6 已超过可签名的最大份数
	 * code = 7 已超过系统可使用期限
	 * code = 8 输入参数不全
	 *
	 * code = 9   上传文件不是PDF文档
	 * code = 10 上传文档超过10M
	 * code = 11 上传文档不存在
	 * code = 12 上传文档已签名
	 * code = 13 插入水印失败
	 * code = 14 公章不存在
	 * code = 15 插入公章失败
	 * code = 16 插入公章、水印时接口异常
	 * code = 17 文档签名失败
	 * code = 18 上传PDF文档异常
	   code = 19 水印图片不存在

	   code = 25 ID不存在
	 * code = 30 插入骑缝章失败
	 * code = 31插入骑缝章失败，公章不存在
	 * code = 98超出系统最大的处理能力MAX_SIGNING_NUMBER
	   code = 99 不受保护的IP地址访问
	 *  code = 100 异常情况
	 */
	@Override
	public String uploadFileAndSignFromFormByID(String json, Attachment pdf) {
		String interfaceName = "uploadFileAndSignFromFormByID";
		RestLogHelper.fnStartDebug(Thread.currentThread().getName(),interfaceName);
		logger.info("Payload:" + json);
		WebServiceResponseInfo info = new WebServiceResponseInfo();
		JSONObject result = null;
		String savePath = "";
		InputStream ins = null;
		try {
			if (isSystemBusy(info, interfaceName)) {
				result= new JSONObject(info);
				return result.toString();
			}
			if(!systemFacade.isIpInVisited(request)){
				info.setCode(99);
				info.setMessage(ResourceUtils.getMessage("MODULES_UNPROTECTED_IP_ADDRESS_ACCESS"));
				result= new JSONObject(info);
				RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
				return result.toString();
			}
			DataHandler dh = pdf.getDataHandler();
			ins = dh.getInputStream();
			if(StringUtil.isEmptyString(dh.getName())){
				info.setCode(8);
				info.setMessage(ResourceUtils.getMessage("MODULES_INPUT_PARAMETER_INCOMPLETE"));
				result= new JSONObject(info);
				RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
				return result.toString();
			}
			/**
			 * 系统存储空间已满
			 */
			if (CebaConfig.FILE_STORAGE_FALG == FileStorageFalgeEnum.START) {
				if (!StorageFileCacheManage.isSystemUseStorageAddress()) {
					info.setCode(100);
					info.setMessage(ResourceUtils.getMessage("STORAGE_ADRESS_USE_ORDER_HINT_MESSAGE"));
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, info);
					result= new JSONObject(info);
					return result.toString();
				}
			}

			String dhName = new String(dh.getName().getBytes("iso-8859-1"),"utf-8");
//            synchronized(lock)
			{
				if(StringUtil.isEmptyString(json)){
					info.setCode(8);
					info.setMessage(ResourceUtils.getMessage("MODULES_INPUT_PARAMETER_INCOMPLETE"));
					result= new JSONObject(info);
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
					return result.toString();
				}
				json = URLDecoder.decode(json,"utf-8");
				RestLogHelper.fnPrintParamDebug(Thread.currentThread().getName(), interfaceName,json, dhName);
				JSONObject obj = new JSONObject(json);
				ISign[] iSigns = null;
				FTPObject ftp= null;

				if(obj.has("sign")){
					if(obj.getJSONObject("sign").has("ID")){
						String iSignId = obj.getJSONObject("sign").getString("ID");
						String[] iSignIds = {iSignId};
						iSigns = new ISign[iSignIds.length];
						info = systemFacade.getSignPDFParamArrayBySignID(iSignIds,iSigns);
						if(info.getCode() !=0){
							result= new JSONObject(info);
							RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
							return result.toString();
						}

						//本次签名是否需要数字签名；isSignature=true，需要数字签名
						String isSignature = obj.getJSONObject("sign").has("isSignature")?obj.getJSONObject("sign").getString("isSignature"):"true";
						boolean isOfd = obj.getJSONObject("sign").optBoolean("isOfd", false);
						String validStartOfSeal = obj.getJSONObject("sign").has("validStartOfSeal")?obj.getJSONObject("sign").getString("validStartOfSeal"):"";
						String validEndOfSeal = obj.getJSONObject("sign").has("validEndOfSeal")?obj.getJSONObject("sign").getString("validEndOfSeal"):"";
						String startPageOfQifeng = obj.getJSONObject("sign").has("startPageOfQifeng")?obj.getJSONObject("sign").getString("startPageOfQifeng"):"";
						String endPageOfQifeng = obj.getJSONObject("sign").has("endPageOfQifeng")?obj.getJSONObject("sign").getString("endPageOfQifeng"):"";
						boolean bNeedSig = true;
						if (isSignature.equalsIgnoreCase("false")) {
							bNeedSig = false;
							logger.info("不需要数字签名！");
						}
						for (ISign iSign : iSigns) {
							iSign.setNeedSinature(bNeedSig);
							iSign.setShouldOfd(isOfd);
							iSign.setValidStartOfSeal(validStartOfSeal);
							iSign.setValidEndOfSeal(validEndOfSeal);
							iSign.setStartPageOfQifeng(startPageOfQifeng);
							iSign.setEndPageOfQifeng(endPageOfQifeng);
							//从接口入参中获取可复制参数 入参allowPdfContentCopy，true-允许 false-不允许
							systemFacade.setAllowPdfContentCopyFromApiParam(iSign, obj.getJSONObject("sign"));
						}
						//从接口入参中获取控制Api签名时关键字没匹配上是否报错
						systemFacade.setNoErrorNotNormalMatchApiKeyFromApiParam(obj.getJSONObject("sign"));
						//从接口入参中获取控制Api签名时是否添加二维码
						systemFacade.setAllowAddQrFromApiParam(obj.getJSONObject("sign"));
						String resExecCustomDate = executeCustomDate(obj, interfaceName, iSigns);
						if (!resExecCustomDate.isEmpty()) {
							return resExecCustomDate;
						}
					}else{
						info.setCode(25);
						info.setMessage("ID"+ResourceUtils.getMessage("MODULES_NON_EXISTENT"));
						result= new JSONObject(info);
						RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
						return result.toString();
					}
					String ftpId = obj.getJSONObject("sign").has("FTPID")?obj.getJSONObject("sign").getString("FTPID"):"";
					if(!StringUtil.isEmptyString(ftpId)){
						ftp = systemFacade.getFTPObjectById(ftpId);
						if(ftp == null){
							info.setCode(26);
							info.setMessage("FTPID"+ResourceUtils.getMessage("MODULES_NON_EXISTENT"));
							result= new JSONObject(info);
							RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
							return result.toString();
						}
						if(!systemFacade.checkFtpValid(ftp)){
							info.setCode(20);
							info.setMessage(ResourceUtils.getMessage("MODULES_FTP_CINFIGURATION_PARAMETER_INCOMPLETE"));
							result= new JSONObject(info);
							RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
							return result.toString();
						}
					}


				}

				String nowDay = DateUtil.getDayTime("", 0);
				String timestamp = DateUtil.getNowTime(DateUtil.YYYYMMDDHHMMSSS) + ID.get12bID();

				savePath = LogicPathUtil.getPhysicalSignFolder(StorageFileCacheManage.getSystemUseAddressId()) + nowDay + "/";
				if (!FileHelper.exists(savePath)) {
					new File(savePath).mkdirs();
				}

				info = systemFacade.checkPdfFileAttr(ins);
				if (info.getCode() != 0) {
					result = new JSONObject(info);
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
					return result.toString();
				}

				boolean flag = false;
				//尝试转换非PDF格式文件
				if (!systemFacade.isPdfFile(dhName)) {
					String tmpName = savePath + IDSFileUtils.getFileName(dhName) + "_" + timestamp;
					String tmpPath = tmpName + "." + IDSFileUtils.getFileExtName(dhName);
					savePath = tmpName + ".pdf";
					IDSFileUtils.writeToFile(ins, tmpPath);
					logger.debug("Begin convert " + tmpPath + " to " + savePath);
					flag = ToPdfUtils.fileToPdf(tmpPath, savePath);
					logger.debug("End convert " + tmpPath + " to " + savePath);
				} else {
					savePath = savePath + IDSFileUtils.getFileName(dhName) + "_" + timestamp + ".pdf";
					flag = IDSFileUtils.writeToFile(ins, savePath);

					//清除加密信息
//					if (!PdfSignUtils.checkFileHasRSASigned(savePath) && !PdfSignUtils.checkFileHasSM2Signed(savePath)) {
//						String delEncryptPath = savePath.replace(".pdf", "_delEncrypt.pdf");
//						PdfTools.deletePDFEncrypt(savePath, delEncryptPath);
//						savePath = delEncryptPath;
//					}
				}

				//获取统计的参数
				ReportSign  parm = systemFacade.packCollectStatisticParm(1, EditionTypeEnum.API.getType(), request.getRemoteAddr());
				if(flag){
					if(iSigns !=null && iSigns.length == 1){
						int key_type = iSigns[0].getKeyType();
						if(key_type == KeyLoaderType.TYPE_CEBA_KEY){
							info = signFacade.checkCanSign();
							if(info.getCode() !=0){
								result= new JSONObject(info);
								return result.toString();
							}

							//下载pdf文档成功，开始插入公章和签名
							info = signFacade.signForUploadFile(iSigns,savePath,ftp,parm);
						}else{
							info = signFacade.dealServerSign(iSigns,savePath,ftp,parm);
						}
					}
				}else{
					info.setMessage(ResourceUtils.getMessage("MODULES_UPLOAD_PDF_DOCUMENT_EXCEPTION"));
					info.setCode(18);
				}

			}
		} catch (Exception e) {
			LoggerHelper.error(logger, e, "");
			info.setMessage(ResourceUtils.getMessage("MODULES_INTERFACE_EXCEPTION"));
			info.setCode(100);
		} finally {
			freeSystemALittle();

			if (ins != null) {
				try {
					ins.close();
				} catch (IOException e) {
					LoggerHelper.error(logger, e, "释放文件资源失败");
				}
			}
		}
		result= new JSONObject(info);
		RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
		return result.toString();
	}

	private String executeCustomDate(JSONObject obj, String interfaceName, ISign[] iSigns) {
		String result = "";
		JSONObject jsonResult;
		Map<String, String> customDateToContent = new HashMap<String, String>();
		// 本次签名是否使用自定义日期章
		if (obj.getJSONObject("sign").has("customDate")) {
			JSONArray customDateObjs=obj.getJSONObject("sign").getJSONArray("customDate");
			if(customDateObjs != null){
				for (int iCustomDate = 0; iCustomDate<customDateObjs.length(); ++iCustomDate) {
					JSONObject customDateObj = customDateObjs.getJSONObject(iCustomDate);

					//判断三个值必须有
					boolean hasDateStampId = customDateObj.has("dateName");
					boolean hasDateContent = customDateObj.has("dateContent");
					if (!hasDateStampId || !hasDateContent) {
						WebServiceResponseInfo wsrInfo = new WebServiceResponseInfo();
						wsrInfo.setCode(8);
						wsrInfo.setMessage(ResourceUtils.getMessage("MODULES_INPUT_PARAMETER_INCOMPLETE"));
						jsonResult = new JSONObject(wsrInfo);
						RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, jsonResult.toString());
						return jsonResult.toString();
					}

					String dateStampId = customDateObj.getString("dateName");
					String dateContent = customDateObj.getString("dateContent");
					//日期和内容非空校验
					if (StringUtils.isBlank(dateStampId) || StringUtils.isBlank(dateContent)) {
						WebServiceResponseInfo wsrInfo = new WebServiceResponseInfo();
						wsrInfo.setCode(8);
						wsrInfo.setMessage(ResourceUtils.getMessage("MODULES_INPUT_PARAMETER_INCOMPLETE"));
						jsonResult = new JSONObject(wsrInfo);
						RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, jsonResult.toString());
						return jsonResult.toString();
					}

					if (iSigns.length > 0) {
						ISign iSignFirst = iSigns[0];
						String otherStampId = iSignFirst.getOtherStampId();
						otherStampId += ",";
						otherStampId += dateStampId;
						iSignFirst.setOtherStampId(otherStampId);
						customDateToContent.put(dateStampId, dateContent);
						iSignFirst.setCustomDateToContent(customDateToContent);
					}
				}
			}
		}

		return result;
	}

	/**
	 * 模拟http表单提交，上传pdf文档,双签名
	 * json
	 * 同时上传一串json字符串(公章信息)
	 * code = 0  签名成功
	 *
	 * code = 1 无法获取证书链
	 * code = 2 证书过期
	 * code = 3 签名企业和初始设置不符
	 * code = 4 签名报告与统计份数不一致
	 * code = 5 无法签名，未激活数字证书签名
	 * code = 6 已超过可签名的最大份数
	 * code = 7 已超过系统可使用期限
	 * code = 8 输入参数不全
	 *
	 * code = 9   上传文件不是PDF文档
	 * code = 10 上传文档超过10M
	 * code = 11 上传文档不存在
	 * code = 12 上传文档已签名
	 * code = 13 插入水印失败
	 * code = 14 公章不存在
	 * code = 15 插入公章失败
	 * code = 16 插入公章、水印时接口异常
	 * code = 17 文档签名失败
	 * code = 18 上传PDF文档异常
	 code = 19 水印图片不存在

	 * code = 30 插入骑缝章失败
	 * code = 31插入骑缝章失败，公章不存在
	 * code = 98 超出系统最大的处理能力MAX_SIGNING_NUMBER
	 code = 99 不受保护的IP地址访问
	 *  code = 100 异常情况
	 */
	@Override
	public String uploadFileAndMultiSignFromFormByID(String json, Attachment pdf) {
		String interfaceName = "uploadFileAndMultiSignFromFormByID";
		RestLogHelper.fnStartDebug(Thread.currentThread().getName(),interfaceName);
		logger.info("Payload:" + json);
		WebServiceResponseInfo info = new WebServiceResponseInfo();
		JSONObject result = null;
		String savePath = "";
		InputStream ins = null;
		try {
			if (isSystemBusy(info, interfaceName)) {
				result= new JSONObject(info);
				return result.toString();
			}
			if(!systemFacade.isIpInVisited(request)){
				info.setCode(99);
				info.setMessage(ResourceUtils.getMessage("MODULES_UNPROTECTED_IP_ADDRESS_ACCESS"));
				result= new JSONObject(info);
				RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
				return result.toString();
			}
			DataHandler dh = pdf.getDataHandler();
			ins = dh.getInputStream();
			if(StringUtil.isEmptyString(dh.getName())){
				info.setCode(8);
				info.setMessage(ResourceUtils.getMessage("MODULES_INPUT_PARAMETER_INCOMPLETE"));
				result= new JSONObject(info);
				RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
				return result.toString();
			}
			/**
			 * 系统存储空间已满
			 */
			if (CebaConfig.FILE_STORAGE_FALG == FileStorageFalgeEnum.START) {
				if (!StorageFileCacheManage.isSystemUseStorageAddress()) {
					info.setCode(100);
					info.setMessage(ResourceUtils.getMessage("STORAGE_ADRESS_USE_ORDER_HINT_MESSAGE"));
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, info);
					result= new JSONObject(info);
					return result.toString();
				}
			}
			String dhName = new String(dh.getName().getBytes("iso-8859-1"),"utf-8");
//            synchronized(lock)
			{
				if(StringUtil.isEmptyString(json)){
					info.setCode(8);
					info.setMessage(ResourceUtils.getMessage("MODULES_INPUT_PARAMETER_INCOMPLETE"));
					result= new JSONObject(info);
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
					return result.toString();
				}
				json = URLDecoder.decode(json,"utf-8");
				RestLogHelper.fnPrintParamDebug(Thread.currentThread().getName(), interfaceName,json, dhName);
				JSONObject obj = new JSONObject(json);
				ISign[] iSigns = null;
				FTPObject ftp= null;

				if(obj.has("sign")){
					if(obj.getJSONObject("sign").has("IDs")){
						String[] iSignIds = obj.getJSONObject("sign").getString("IDs").trim().split(",");
						iSigns = new ISign[iSignIds.length];
						info = systemFacade.getSignPDFParamArrayBySignID(iSignIds,iSigns);
						if(info.getCode() !=0){
							result= new JSONObject(info);
							RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
							return result.toString();
						}

						//本次签名是否需要数字签名；isSignature=true，需要数字签名
						String isSignature = obj.getJSONObject("sign").has("isSignature")?obj.getJSONObject("sign").getString("isSignature"):"true";
						boolean isOfd = obj.getJSONObject("sign").optBoolean("isOfd", false);
						String validStartOfSeal = obj.getJSONObject("sign").has("validStartOfSeal")?obj.getJSONObject("sign").getString("validStartOfSeal"):"";
						String validEndOfSeal = obj.getJSONObject("sign").has("validEndOfSeal")?obj.getJSONObject("sign").getString("validEndOfSeal"):"";
						String startPageOfQifeng = obj.getJSONObject("sign").has("startPageOfQifeng")?obj.getJSONObject("sign").getString("startPageOfQifeng"):"";
						String endPageOfQifeng = obj.getJSONObject("sign").has("endPageOfQifeng")?obj.getJSONObject("sign").getString("endPageOfQifeng"):"";
						boolean bNeedSig = true;
						// 最后一个设置的签名是否需要数字签名还是普通签名
						boolean isLastSig = true;
						if (isSignature.equalsIgnoreCase("false")) {
							bNeedSig = false;
						} else if (isSignature.equalsIgnoreCase("allNormal")) {
							bNeedSig = false;
							isLastSig = false;
						}

						if (bNeedSig) {
							for (ISign iSign : iSigns) {
								iSign.setNeedSinature(true);
							}
						} else {
							int i=0;
							for (; i<iSigns.length - 1; ++i) {
								iSigns[i].setNeedSinature(false);
							}
							if (isLastSig) {
								iSigns[i].setNeedSinature(true);    //最后一个设置的数字签名不能忽略
								iSigns[i].setShouldOfd(isOfd);
								iSigns[i].setValidStartOfSeal(validStartOfSeal);
								iSigns[i].setValidEndOfSeal(validEndOfSeal);
							} else {
								iSigns[i].setNeedSinature(false);
							}
						}

						for (ISign iSign : iSigns) {
							iSign.setStartPageOfQifeng(startPageOfQifeng);
							iSign.setEndPageOfQifeng(endPageOfQifeng);
							//从接口入参中获取可复制参数 入参allowPdfContentCopy，true-允许 false-不允许
							systemFacade.setAllowPdfContentCopyFromApiParam(iSign, obj.getJSONObject("sign"));
						}
					    //从接口入参中获取控制Api签名时关键字没匹配上是否报错
						systemFacade.setNoErrorNotNormalMatchApiKeyFromApiParam(obj.getJSONObject("sign"));
						//从接口入参中获取控制Api签名时是否添加二维码
						systemFacade.setAllowAddQrFromApiParam(obj.getJSONObject("sign"));
						String resExecCustomDate = executeCustomDate(obj, interfaceName, iSigns);
						if (!resExecCustomDate.isEmpty()) {
							return resExecCustomDate;
						}
					}else{
						info.setCode(25);
						info.setMessage("ID"+ResourceUtils.getMessage("MODULES_NON_EXISTENT"));
						result= new JSONObject(info);
						RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
						return result.toString();
					}
					String ftpId = obj.getJSONObject("sign").has("FTPID")?obj.getJSONObject("sign").getString("FTPID"):"";
					if(!StringUtil.isEmptyString(ftpId)){
						ftp = systemFacade.getFTPObjectById(ftpId);
						if(ftp == null){
							info.setCode(26);
							info.setMessage("FTPID"+ResourceUtils.getMessage("MODULES_NON_EXISTENT"));
							result= new JSONObject(info);
							RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
							return result.toString();
						}
						if(!systemFacade.checkFtpValid(ftp)){
							info.setCode(20);
							info.setMessage(ResourceUtils.getMessage("MODULES_FTP_CINFIGURATION_PARAMETER_INCOMPLETE"));
							result= new JSONObject(info);
							RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
							return result.toString();
						}
					}


				}

				String nowDay = DateUtil.getDayTime("", 0);
				String timestamp = DateUtil.getNowTime(DateUtil.YYYYMMDDHHMMSSS) + ID.get12bID();

				savePath = LogicPathUtil.getPhysicalSignFolder(StorageFileCacheManage.getSystemUseAddressId()) + nowDay + "/";
				if (!FileHelper.exists(savePath)) {
					new File(savePath).mkdirs();
				}

				info = systemFacade.checkPdfFileAttr(ins);
				if (info.getCode() != 0) {
					result = new JSONObject(info);
					RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
					return result.toString();
				}

				boolean flag = false;
				//尝试转换非PDF格式文件
				if (!systemFacade.isPdfFile(dhName)) {
					String tmpName = savePath + IDSFileUtils.getFileName(dhName) + "_" + timestamp;
					String tmpPath = tmpName + "." + IDSFileUtils.getFileExtName(dhName);
					savePath = tmpName + ".pdf";
					IDSFileUtils.writeToFile(ins, tmpPath);
					logger.debug("Begin convert " + tmpPath + " to " + savePath);
					flag = ToPdfUtils.fileToPdf(tmpPath, savePath);
					logger.debug("End convert " + tmpPath + " to " + savePath);
				} else {
					savePath = savePath + IDSFileUtils.getFileName(dhName) + "_" + timestamp + ".pdf";
					flag = IDSFileUtils.writeToFile(ins, savePath);

					//清除加密信息
					/*if (!PdfSignUtils.checkFileHasRSASigned(savePath) && !PdfSignUtils.checkFileHasSM2Signed(savePath)) {
						String delEncryptPath = savePath.replace(".pdf", "_delEncrypt.pdf");
						PdfTools.deletePDFEncrypt(savePath, delEncryptPath);
						savePath = delEncryptPath;
					}*/
				}

				//获取统计的参数
				ReportSign  parm = systemFacade.packCollectStatisticParm(1, EditionTypeEnum.API.getType(), request.getRemoteAddr());
				if(flag){
					//判断是基本模式还是高级模式
					if(iSigns !=null && iSigns.length == 1){
						int key_type = iSigns[0].getKeyType();
						if(key_type == KeyLoaderType.TYPE_CEBA_KEY){
							info = signFacade.checkCanSign();
							if(info.getCode() !=0){
								result= new JSONObject(info);
								return result.toString();
							}

							//下载pdf文档成功，开始插入公章和签名
							info = signFacade.signForUploadFile(iSigns,savePath,ftp,parm);
						}else{
							info = signFacade.dealServerSign(iSigns,savePath,ftp,parm);
						}
					}else{
						info = signFacade.dealServerSign(iSigns,savePath,ftp,parm);
					}
				}else{
					info.setMessage(ResourceUtils.getMessage("MODULES_UPLOAD_PDF_DOCUMENT_EXCEPTION"));
					info.setCode(18);
					logger.debug(info.getMessage());
				}
			}
		} catch (Exception e) {
			LoggerHelper.error(logger, e, "");
			info.setMessage(ResourceUtils.getMessage("MODULES_INTERFACE_EXCEPTION"));
			info.setCode(100);
		} finally {
			freeSystemALittle();

			if (ins != null) {
				try {
					ins.close();
				} catch (IOException e) {
					LoggerHelper.error(logger, e, "释放文件资源失败");
				}
			}
		}

		result= new JSONObject(info);
		RestLogHelper.fnEndDebug(Thread.currentThread().getName(), interfaceName, result.toString());
		return result.toString();
	}


}
